import React, { useEffect, useRef, useState } from 'react';
import {
    View,
    Image,
    Text,
    StyleSheet,
    Animated,
    Easing,
    StyleProp,
    ViewStyle,
    ImageStyle,
    TextStyle,
    Pressable,
} from 'react-native';

type AvatarGroupsProps = {
    urls?: string[];
    count?: number;
    size?: number;
    maxVisible?: number;
    avatarStyle?: StyleProp<ImageStyle>;
    containerStyle?: StyleProp<ViewStyle>;
    animationDuration?: number;
    overlapRatio?: number;
    showRemaining?: boolean;
    remainingContainerStyle?: StyleProp<ViewStyle>;
    remainingTextStyle?: StyleProp<TextStyle>;
    animationType?: 'fade' | 'scale';
    rotationInterval?: number;
    onPress?: any;
};

const AvatarGroups: React.FC<AvatarGroupsProps> = ({
    urls = [],
    count = urls.length,
    size = 50,
    maxVisible = 3,
    avatarStyle = {},
    containerStyle = {},
    animationDuration = 300,
    overlapRatio = 0.4,
    showRemaining = true,
    remainingContainerStyle = {},
    remainingTextStyle = {},
    animationType = 'slide',
    rotationInterval = 0,
    onPress,
}) => {
    const visibleAvatars = urls.slice(0, maxVisible);
    const remainingCount = Math.max(count - visibleAvatars.length, 0);

    // Use refs to maintain animation values
    const positionAnims = useRef<Animated.Value[]>([]);
    const fadeAnims = useRef<Animated.Value[]>([]);
    const scaleAnims = useRef<Animated.Value[]>([]);
    const rotationAnim = useRef(new Animated.Value(0));
    const animationRefs = useRef<Animated.CompositeAnimation[]>([]);

    // Initialize animation values
    if (positionAnims.current.length !== visibleAvatars.length) {
        positionAnims.current = visibleAvatars.map(() => new Animated.Value(0));
        fadeAnims.current = visibleAvatars.map(() => new Animated.Value(0));
        scaleAnims.current = visibleAvatars.map(() => new Animated.Value(0.8));
    }

    const [rotationIndex, setRotationIndex] = useState(0);

    useEffect(() => {
        // Clean up any running animations
        animationRefs.current.forEach((anim) => anim.stop());
        animationRefs.current = [];

        const animations = visibleAvatars.map((_, index) => {
            let animation;

            switch (animationType) {
                case 'fade':
                    animation = Animated.timing(fadeAnims.current[index], {
                        toValue: 1,
                        duration: animationDuration,
                        easing: Easing.out(Easing.quad),
                        useNativeDriver: true,
                    });
                    break;
                case 'scale':
                    animation = Animated.timing(scaleAnims.current[index], {
                        toValue: 1,
                        duration: animationDuration,
                        easing: Easing.out(Easing.quad),
                        useNativeDriver: true,
                    });
                    break;
                default:
                    animation = Animated.timing(positionAnims.current[index], {
                        toValue: 1,
                        duration: animationDuration,
                        easing: Easing.out(Easing.quad),
                        useNativeDriver: true,
                    });
            }

            return Animated.sequence([Animated.delay(index * 100), animation]);
        });

        const parallelAnim = Animated.parallel(animations);
        animationRefs.current.push(parallelAnim);
        parallelAnim.start();

        return () => {
            animationRefs.current.forEach((anim) => anim.stop());
        };
    }, [visibleAvatars, animationType, animationDuration]);

    useEffect(() => {
        if (!rotationInterval || urls.length <= maxVisible) return;

        const interval = setInterval(() => {
            setRotationIndex((prev) => (prev + 1) % urls.length);

            const sequence = Animated.sequence([
                Animated.timing(rotationAnim.current, {
                    toValue: 1,
                    duration: animationDuration / 2,
                    easing: Easing.out(Easing.quad),
                    useNativeDriver: true,
                }),
                Animated.timing(rotationAnim.current, {
                    toValue: 0,
                    duration: animationDuration / 2,
                    easing: Easing.in(Easing.quad),
                    useNativeDriver: true,
                }),
            ]);

            animationRefs.current.push(sequence);
            sequence.start();
        }, rotationInterval);

        return () => {
            clearInterval(interval);
            animationRefs.current.forEach((anim) => anim.stop());
        };
    }, [urls, rotationInterval, maxVisible, animationDuration]);

    const getAnimatedStyle = (index: number) => {
        const overlap = size * overlapRatio;
        const baseLeft = index * (size - overlap);

        switch (animationType) {
            case 'fade':
                return {
                    opacity: fadeAnims.current[index],
                    left: baseLeft,
                    transform: [
                        {
                            translateX: rotationAnim.current.interpolate({
                                inputRange: [0, 1],
                                outputRange: [0, -10 * (index % 2 === 0 ? 1 : -1)],
                            }),
                        },
                    ],
                };
            case 'scale':
                return {
                    left: baseLeft,
                    transform: [
                        {
                            scale: scaleAnims.current[index],
                        },
                        {
                            translateX: rotationAnim.current.interpolate({
                                inputRange: [0, 1],
                                outputRange: [0, -5 * (index % 2 === 0 ? 1 : -1)],
                            }),
                        },
                    ],
                };

            default:
                return {
                    left: positionAnims.current[index].interpolate({
                        inputRange: [0, 1],
                        outputRange: [size, baseLeft],
                    }),
                    transform: [
                        {
                            translateX: rotationAnim.current.interpolate({
                                inputRange: [0, 1],
                                outputRange: [0, -5 * (index % 2 === 0 ? 1 : -1)],
                            }),
                        },
                    ],
                };
        }
    };

    const getAvatarSource = (index: number) => {
        const actualIndex = (rotationIndex + index) % urls.length;
        return { uri: urls[actualIndex] };
    };

    return (
        <Pressable style={[styles.container, { height: size }, containerStyle]} onPress={onPress}>
            {visibleAvatars.map((_, index) => (
                <Animated.Image
                    key={`avatar-${index}`}
                    source={getAvatarSource(index)}
                    style={[
                        styles.avatar,
                        {
                            width: size,
                            height: size,
                            borderRadius: size / 2,
                            zIndex: visibleAvatars.length - index,
                        },
                        avatarStyle,
                        getAnimatedStyle(index),
                    ]}
                    onError={() => console.warn(`Failed to load avatar at index ${index}`)}
                />
            ))}

            {showRemaining && remainingCount > 0 && (
                <Animated.View
                    style={[
                        styles.remainingContainer,
                        {
                            width: size,
                            height: size,
                            borderRadius: size / 2,
                            left: visibleAvatars.length * (size - size * overlapRatio),
                            opacity: rotationAnim.current.interpolate({
                                inputRange: [0, 1],
                                outputRange: [1, 0.7],
                            }),
                            transform: [
                                {
                                    scale: rotationAnim.current.interpolate({
                                        inputRange: [0, 1],
                                        outputRange: [1, 1.1],
                                    }),
                                },
                            ],
                        },
                        remainingContainerStyle,
                    ]}>
                    <Text style={[styles.remainingText, { fontSize: size * 0.35 }, remainingTextStyle]}>
                        +{remainingCount}
                    </Text>
                </Animated.View>
            )}
        </Pressable>
    );
};

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        alignItems: 'center',
        position: 'relative',
    },
    avatar: {
        position: 'absolute',
        borderWidth: 2,
        borderColor: 'white',
    },
    remainingContainer: {
        position: 'absolute',
        backgroundColor: '#cccccc',
        justifyContent: 'center',
        alignItems: 'center',
    },
    remainingText: {
        color: 'white',
        fontWeight: 'bold',
    },
});

export default AvatarGroups;
